#include "ASScrollBar.h"

#define ASS_SCROLLBAR_DEFAULT_MIN_SHOW_LEN 4

static as_ret as_ctrl_scrollbar_set_img(as_control* ctrl_p,
                                        ASWSTR tail_path,
                                        ASWSTR tile_path,
                                        as_image_src_type type)
{
    as_scrollbar* sb_p = (as_scrollbar*)ctrl_p;

    if(!sb_p)
        return AS_INVALID_PARAM;

    if(!tail_path || as_wstrlen(tail_path) <= 0 || !tile_path || as_wstrlen(tile_path) <= 0)
        return AS_INVALID_PARAM;

    sb_p->tail_img = as_ctrl_image_create(sb_p->base.area, type, tail_path, ASFALSE);
    sb_p->tile_img = as_ctrl_image_create(sb_p->base.area, type, tile_path, ASFALSE);

    if(!sb_p->tail_img || !sb_p->tile_img)
        return AS_INTERNAL_ERROR;
    else
    {
        sb_p->tile_img->set_show_type((as_control*)sb_p->tile_img, AS_IMAGE_TILED);

        if(sb_p->layout == AS_SCROLLBAR_VERTICAL)
        {
            sb_p->fix_value = sb_p->tile_img->img_w;
            sb_p->min_len = sb_p->tail_img->img_h;
        }
        else//if(sb_p->layout == AS_SCROLLBAR_HORIZONTAL)
        {
            sb_p->fix_value = sb_p->tile_img->img_h;
            sb_p->min_len = sb_p->tail_img->img_w;
        }

        return AS_OK;
    }
}

static as_ret as_ctrl_scrollbar_set_color(as_control* ctrl_p, ASUINT color)
{
    as_scrollbar* sb_p = (as_scrollbar*)ctrl_p;

    if(!sb_p)
        return AS_INVALID_PARAM;

    sb_p->color = color;
    return AS_OK;
}

static void as_ctrl_scrollbar_calc_show_area(as_control* ctrl_p)
{
    as_scrollbar* sb_p = (as_scrollbar*)ctrl_p;
    ASUINT total_height;

    if(!sb_p)
        return;

    total_height = sb_p->hh1 + sb_p->sh + sb_p->hh2;//adjust the total height

    //vertical layout
    if(sb_p->layout == AS_SCROLLBAR_VERTICAL)
    {
        sb_p->show_area.w = sb_p->fix_value;
        sb_p->show_area.x = sb_p->base.area.x + sb_p->base.area.w - 1 - sb_p->show_area.w;

        if(total_height == sb_p->sh)
        {
            sb_p->show_area.y = sb_p->base.area.y;
            sb_p->show_area.h = sb_p->base.area.h;
        }
        else
        {
            ASINT h_adjust;
            sb_p->show_area.h = (ASUINT16)(sb_p->sh * sb_p->base.area.h / total_height);
            sb_p->show_area.y = (ASINT16)(sb_p->base.area.y + (sb_p->hh1 * sb_p->base.area.h / total_height));
            h_adjust = sb_p->show_area.h - sb_p->min_len;

            if(h_adjust < 0)
            {
                sb_p->show_area.h += (ASINT16) - h_adjust;

                if(sb_p->show_area.y - sb_p->base.area.y > -h_adjust)
                    sb_p->show_area.y -= (ASINT16) - h_adjust;
            }
        }
    }
    else //if(sb_p->layout == AS_SCROLLBAR_HORIZONTAL)
    {
        sb_p->show_area.h = sb_p->fix_value;
        sb_p->show_area.y = sb_p->base.area.y + sb_p->base.area.h - 1 - sb_p->show_area.h;

        if(total_height == sb_p->sh)
        {
            sb_p->show_area.x = sb_p->base.area.x;
            sb_p->show_area.w = sb_p->base.area.w;
        }
        else
        {
            ASINT h_adjust;
            sb_p->show_area.w = (ASUINT16)(sb_p->sh * sb_p->base.area.w / total_height);
            sb_p->show_area.x = (ASINT16)(sb_p->base.area.x + (sb_p->hh1 * sb_p->base.area.w / total_height));
            h_adjust = sb_p->show_area.w - sb_p->min_len;

            if(h_adjust < 0)
            {
                sb_p->show_area.w += (ASINT16) - h_adjust;

                if(sb_p->show_area.x - sb_p->base.area.x > -h_adjust)
                    sb_p->show_area.x -= (ASINT16) - h_adjust;
            }
        }
    }
}

static as_ret as_ctrl_scrollbar_set_value(as_control* ctrl_p, ASUINT hh1, ASUINT sh, ASUINT hh2)
{
    as_scrollbar* sb_p = (as_scrollbar*)ctrl_p;

    if(!sb_p)
        return AS_INVALID_PARAM;

    sb_p->hh1 = hh1;
    sb_p->sh = sh;
    sb_p->hh2 = hh2;
    //calc show area
    as_ctrl_scrollbar_calc_show_area(ctrl_p);
    return AS_OK;
}

static void as_ctrl_scrollbar_paint(as_control* ctrl_p)
{
    as_scrollbar* sb_p = (as_scrollbar*)ctrl_p;

    if(!sb_p)
        return;

    if(sb_p->tail_img && sb_p->tile_img)
    {
        if(sb_p->layout == AS_SCROLLBAR_VERTICAL)
        {
            if(sb_p->show_area.h <= sb_p->min_len)
            {
                sb_p->tail_img->base.move((as_control*)sb_p->tail_img, sb_p->show_area.x, sb_p->show_area.y);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
            }
            else
            {
                as_rect area;
                ASINT layer;
                layer = sb_p->base.show_hdlr;
                memcpy(&area, &sb_p->show_area, sizeof(as_rect));
                area.h = (ASINT16)sb_p->min_len >> 1;
                as_set_layer_clip_ex(layer, &area);
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
                as_reset_layer_clip(layer);
                area.y = sb_p->show_area.y + (ASINT16)(sb_p->min_len >> 1);
                area.h = sb_p->show_area.h - (ASINT16)sb_p->min_len;
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                as_set_layer_clip_ex(layer, &area);
                sb_p->tile_img->base.paint_hdlr((as_control*)sb_p->tile_img);
                as_reset_layer_clip(layer);
                area.y += area.h;
                area.h = (ASINT16)sb_p->min_len >> 1;
                as_set_layer_clip_ex(layer, &area);
                area.y -= (ASINT16)(sb_p->min_len >> 1);
                area.h += area.h;
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
            }
        }
        else //if(sb_p->layout == AS_SCROLLBAR_HORIZONTAL)
        {
            if(sb_p->show_area.w <= sb_p->min_len)
            {
                sb_p->tail_img->base.move((as_control*)sb_p->tail_img, sb_p->show_area.x, sb_p->show_area.y);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
            }
            else
            {
                as_rect area;
                ASINT layer;
                layer = sb_p->base.show_hdlr;
                memcpy(&area, &sb_p->show_area, sizeof(as_rect));
                area.w = (ASINT16)sb_p->min_len >> 1;
                as_set_layer_clip_ex(layer, &area);
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
                as_reset_layer_clip(layer);
                area.x = sb_p->show_area.x + (ASINT16)(sb_p->min_len >> 1);
                area.w = sb_p->show_area.w - (ASINT16)sb_p->min_len;
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                as_set_layer_clip_ex(layer, &area);
                sb_p->tile_img->base.paint_hdlr((as_control*)sb_p->tile_img);
                as_reset_layer_clip(layer);
                area.x += area.w;
                area.w = (ASINT16)sb_p->min_len >> 1;
                as_set_layer_clip_ex(layer, &area);
                area.x -= (ASINT16)(sb_p->min_len >> 1);
                area.w += area.w;
                sb_p->tail_img->base.change_area_hdlr((as_control*)sb_p->tail_img, area);
                sb_p->tail_img->base.paint_hdlr((as_control*)sb_p->tail_img);
            }
        }
    }
    else
    {
        as_fill_rect(&sb_p->show_area, sb_p->color, sb_p->color);
    }
}

static void as_ctrl_scrollbar_set_hidden(as_control* ctrl_p, ASINT if_hidden)
{
}

as_scrollbar* as_ctrl_scrollbar_create(as_rect area, as_scrollbar_layout layout)
{
    as_scrollbar* sb_p;
    sb_p = as_calloc(sizeof(as_scrollbar));

    if(!sb_p)
        return ASNULL;

    as_ctrl_init((as_control*)sb_p, area);
    sb_p->base.paint_hdlr = as_ctrl_scrollbar_paint;
    sb_p->base.set_hidden = as_ctrl_scrollbar_set_hidden;
    sb_p->base.ctrl_type = AS_CTRL_SCROLLBAR;

    if(sb_p->layout == AS_SCROLLBAR_VERTICAL)
        sb_p->fix_value = area.w;
    else if(sb_p->layout == AS_SCROLLBAR_HORIZONTAL)
        sb_p->fix_value = area.h;

    sb_p->min_len = ASS_SCROLLBAR_DEFAULT_MIN_SHOW_LEN;
    sb_p->set_color = as_ctrl_scrollbar_set_color;
    sb_p->set_img = as_ctrl_scrollbar_set_img;
    sb_p->set_value = as_ctrl_scrollbar_set_value;
    return sb_p;
}

as_ret as_ctrl_scrollbar_destory(as_scrollbar* sb_p)
{
    if(!sb_p)
        return AS_INVALID_PARAM;

    if(sb_p->tail_img)
        as_ctrl_destroy((as_control*)sb_p->tail_img);

    if(sb_p->tile_img)
        as_ctrl_destroy((as_control*)sb_p->tile_img);

    as_free(sb_p);
    return AS_OK;
}